package megrez.job.custom.component;

import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

import megrez.job.custom.domain.Config;
import megrez.job.custom.utils.TaskStateException;


/**
 * 计划任务容器
 * 
 * @author Lucky Yang
 * @since 2.6.9
 */
public class ScheduledTaskContainer {
    private final Map<Task, ScheduledFutureTaskHolder> cache = new ConcurrentHashMap<>();

    private static final ScheduledTaskContainer INST = new ScheduledTaskContainer();

    public static Optional<Entry<Task, ScheduledFutureTaskHolder>> getEntry(Config config) {
        return INST.cache.entrySet().stream().filter(entry -> entry.getKey().getConfig().equals(config)).findFirst();
    }

    public static boolean contains(Task task) {
        return INST.cache.containsKey(task);
    }

    public static synchronized void remove(Task task) {
        if(isStarted(task)){
            throw new TaskStateException();
        }

        INST.cache.remove(task);
    }

    public static synchronized void put(Task task, ScheduledFutureTaskHolder holder) {
        if(isStarted(task)){
            throw new TaskStateException();
        }
        // 需要更新key对象
        INST.cache.remove(task);
        INST.cache.put(task, holder);
    }

    public static Optional<ScheduledFutureTaskHolder> get(Task task) {
        return Optional.ofNullable(INST.cache.get(task));
    }

    public static boolean isStopped(Task task) {
        Optional<ScheduledFutureTaskHolder> holder = get(task);
        return holder.isEmpty() || holder.get().isStopped();
    }

    public static boolean isStarted(Task task) {
        return !isStopped(task);
    }

    public static Set<Task> getTasks() {
        return INST.cache.keySet();
    }

    public static void loopInContainer(Consumer<Entry<Task, ScheduledFutureTaskHolder>> consumer) {
        INST.cache.entrySet().forEach(consumer);
    }

    public static int size() {
        return INST.cache.size();
    }
}
